#include <boost/bind.hpp>

#include "button.hpp"
#include "foreach.hpp"
#include "formatter.hpp"
#include "grid_widget.hpp"
#include "image_widget.hpp"
#include "label.hpp"
#include "player.hpp"
#include "raster.hpp"
#include "scenario.hpp"
#include "scenario_setup_screen.hpp"
#include "unit_utils.hpp"

namespace game {


scenario_setup_screen::scenario_setup_screen(scenario& scenario, ScenarioCarryoverState& state)
  : gui::dialog(0, 0, graphics::screen_width(), graphics::screen_height()),
    scenario_(scenario), state_(state)
{
	init();
}

namespace {
void build_commander_widgets(const_commander_unit_ptr commander, std::vector<gui::widget_ptr>& widgets)
{
	using namespace gui;
	widgets.push_back(widget_ptr(new image_widget(get_unit_image(*commander))));
}
}

void scenario_setup_screen::init()
{
	clear();

	using namespace gui;
	add_widget(label::create(scenario_.title(), graphics::color_yellow(), 28), 20, 20);

	if(scenario_.players().empty()) {
		return;
	}

	dialog* commanders_dialog = new dialog(0, 0, 924, 360);
	const player& pc = *scenario_.players().front();
	const int MaxUnitsPerCommander = 8;
	
	foreach(commander_unit_ptr commander, pc.commanders()) {
		grid_ptr recruit_grid(new grid(2 + MaxUnitsPerCommander + commander->recruits().size()));
		recruit_grid->add_col(widget_ptr(new image_widget(get_unit_image(*commander))));
		for(int n = 0; n != MaxUnitsPerCommander; ++n) {
			graphics::texture t;
			if(n < commander->soldiers().size()) {
				t = get_unit_image(*commander->soldiers()[n]);
			} else {
				t = graphics::texture::get("units/blank.png");
			}

			//reduce the size to the center part so we can fit things in.
			t = t.get_portion(10, 0, 62, t.height());

			recruit_grid->add_col(widget_ptr(new image_widget(t)));
		}

		recruit_grid->add_col(widget_ptr(label::create("Recruit: ", graphics::color_yellow())));
		foreach(const_soldier_unit_type_ptr type, commander->recruits()) {
			grid_ptr button_grid(new grid(2));
			widget_ptr img(new image_widget(get_unit_image(*type)));
			button_ptr recruit_button(new button(img, boost::bind(&scenario_setup_screen::recruit, this, commander, type)));
			button_grid->add_col(recruit_button);
			if(commander->soldiers().size() >= MaxUnitsPerCommander || type->cost() > state_.gold) {
				recruit_button->set_enabled(false);
			}

			grid_ptr stats_grid(new grid(2));
			stats_grid->set_hpad(5);

			stats_grid->add_col(label::create(type->description(), graphics::color_yellow())).add_col()
			           .add_col(label::create("Attack", graphics::color_yellow()))
			           .add_col(label::create(formatter() << type->attack(), graphics::color_yellow()))
			           .add_col(label::create("Defense", graphics::color_yellow()))
					   .add_col(label::create(formatter() << type->defense(), graphics::color_yellow()))
			           .add_col(label::create("Moves", graphics::color_yellow()))
					   .add_col(label::create(formatter() << type->movement(), graphics::color_yellow()))
			           .add_col(label::create("Cost", graphics::color_yellow()))
					   .add_col(label::create(formatter() << type->cost(), graphics::color_yellow()));


			button_grid->add_col(stats_grid);

			recruit_grid->add_col(button_grid);
		}

		commanders_dialog->add_widget(recruit_grid);
	}

	add_widget(widget_ptr(commanders_dialog));

	dialog* objectives_dialog = new dialog(0, 0, 200, 200);
	objectives_dialog->add_widget(label::create("Objectives", graphics::color_yellow(), 24), 10, 10);
	objectives_dialog->add_widget(label::create("Victory", graphics::color_green(), 18));
	foreach(const scenario::Condition& condition, scenario_.victory_conditions()) {
		objectives_dialog->add_widget(label::create(condition.description, graphics::color_green()));
	}
	objectives_dialog->add_widget(label::create("Defeat", graphics::color_red(), 18));
	foreach(const scenario::Condition& condition, scenario_.defeat_conditions()) {
		objectives_dialog->add_widget(label::create(condition.description, graphics::color_red()));
	}

	add_widget(widget_ptr(objectives_dialog), dialog::MOVE_RIGHT);

	std::vector<widget_ptr> allies, enemies;
	for(int n = 1; n < scenario_.players().size(); ++n) {
		const player& player = *scenario_.players()[n];
		std::vector<widget_ptr>& v = player.is_hostile(*scenario_.players().front()) ? enemies : allies;
		foreach(const_commander_unit_ptr commander, player.commanders()) {
			build_commander_widgets(commander, v);
		}
	}

	grid_ptr allies_grid(new grid(allies.size())), enemies_grid(new grid(enemies.size()));
	foreach(widget_ptr w, allies) {
		allies_grid->add_col(w);
	}

	foreach(widget_ptr w, enemies) {
		enemies_grid->add_col(w);
	}

	dialog* enemies_dialog = new dialog(0, 0, 400, 120);
	enemies_dialog->add_widget(label::create("Enemies", graphics::color_red(), 24), 10, 5);
	enemies_dialog->add_widget(enemies_grid);
	add_widget(widget_ptr(enemies_dialog));

	dialog* allies_dialog = new dialog(0, 0, 400, 120);
	allies_dialog->add_widget(label::create("Allies", graphics::color_green(), 24), 10, 5);
	allies_dialog->add_widget(allies_grid);
	add_widget(widget_ptr(allies_dialog));

	const int right_edge = commanders_dialog->x() + commanders_dialog->width();
	const int bottom_edge = allies_dialog->y() + allies_dialog->height();

	dialog* state_dialog = new dialog(0, 0, 140, 30);
	state_dialog->add_widget(label::create(formatter() << "Gold: " << state_.gold, graphics::color_yellow(), 24), 10, 2);
	add_widget(widget_ptr(state_dialog), right_edge - state_dialog->width(), 20);

	widget_ptr begin_scenario_button(new button(label::create("Begin Scenario", graphics::color_yellow()), boost::bind(&dialog::close, this)));
	add_widget(begin_scenario_button, right_edge - begin_scenario_button->width(), bottom_edge - begin_scenario_button->height());
}

void scenario_setup_screen::recruit(commander_unit_ptr commander, const_soldier_unit_type_ptr type)
{
	state_.gold -= type->cost();
	commander->add_soldier(soldier_unit_ptr(new soldier_unit(*commander, type)));
	init();
}

}
